﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KishOnlineCommone;
using KishOnlineDataAccess;
using KishOnlineCommone.CarDTOs;
using System.Reflection;
using System.Transactions;
using KishOnlineDomain.Common;
using System.Linq.Expressions;
using System.Configuration;

namespace KishOnlineDomain.Domain
{
    /// <summary>
    /// Define CRUD pattern
    /// </summary>
    /// <typeparam name="TDTO">Type of ClassDTO which it's CRUD must impelement</typeparam>
    public class CRUD<TDTO, TDB>
    {
        public ResultDTO<int> Add(TDTO Object)
        {
            Type DTOType = typeof(TDTO);
            Type DBType = typeof(TDB);
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                try
                {
                    System.Data.Linq.ITable TableObject = db.GetTable(DBType);
                    TDB DBObject = Activator.CreateInstance<TDB>();
                    foreach (PropertyInfo Prop in DTOType.GetProperties())
                    {
                        object Value = Prop.GetValue(Object, null);
                        if (Value != null && DBType.GetProperty(Prop.Name) != null &&// DBType.GetProperty(Prop.Name).PropertyType == DBType.GetProperty(Prop.Name).PropertyType
                            (Prop.PropertyType.IsGenericType && Prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)
                             || Value.GetType() == DBType.GetProperty(Prop.Name).PropertyType))
                            DBType.GetProperty(Prop.Name).SetValue(DBObject, Value, null);
                    }
                    TableObject.InsertOnSubmit(DBObject);
                    db.SubmitChanges();
                    int InsertedID;
                    if (DBType.GetProperty("ID") != null)
                    {
                        var InsertedIDObj = DBObject.GetType().GetProperty("ID").GetValue(DBObject, null);
                        
                        if (InsertedIDObj.GetType().Name.ToUpper() == "INT16")
                        {
                            InsertedID = (int)(short)(InsertedIDObj);
                        }
                        else if (InsertedIDObj.GetType().Name.ToUpper() == "INT32")
                        {
                            InsertedID = (int)(InsertedIDObj);
                        }
                        else
                        {
                            InsertedID = (int)(long)(InsertedIDObj);
                        }
                    }
                    else
                    {
                        InsertedID = -1;
                    }
                    return new ResultDTO<int> { Data = (int)(InsertedID), IsSucceed = true, Message = MessageReader.Get(MessageType.Event,17 ) };
                }
                catch(Exception ex)
                {
                    var Meesage = Utility.logError(ex, 33, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                    return new ResultDTO<int> { Data= -1, IsSucceed= Meesage.IsSucceed, Message= Meesage.Message };
                }
            }
        }
        public ResultDTO Update(TDTO Object)
        {
            Type DTOType = typeof(TDTO);
            Type DBType = typeof(TDB);
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                try
                {
                    System.Data.Linq.ITable TableObject = db.GetTable(DBType);
                    var ID = Object.GetType().GetProperty("ID").GetValue(Object, null);
                    //TDB DBObject = TableObject.OfType<TDB>().Where(q =>
                    //    q.GetType().GetProperty("ID").GetValue(q, null).Equals(ID)).SingleOrDefault();
                    TDB DBObject = TableObject.OfType<TDB>().Where(MakeFilter("ID",ID)).SingleOrDefault();
                    if (DBObject != null)
                    {
                        foreach (PropertyInfo Prop in DTOType.GetProperties())
                        {
                            object Value = Prop.GetValue(Object, null);
                            if (Value != null && DBType.GetProperty(Prop.Name) != null //&& DBType.GetProperty(Prop.Name).PropertyType == DBType.GetProperty(Prop.Name).PropertyType)
                               && (Prop.PropertyType.IsGenericType && Prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)
                             || Value.GetType() == DBType.GetProperty(Prop.Name).PropertyType))
                                DBType.GetProperty(Prop.Name).SetValue(DBObject, Value, null);
                        }
                        db.SubmitChanges();
                        return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 18) };
                    }
                    else
                    {
                        return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 49) };
                    }
                }
                catch(Exception ex)
                {
                    return Utility.logError(ex, 34, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                }
            }
        }
        public ResultDTO Delete(int ID)
        {
            Type DBType = typeof(TDB);
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                try
                {
                    System.Data.Linq.ITable TableObject = db.GetTable(DBType);
                    //TDB DBObject = TableObject.OfType<TDB>().ToList().Where(q =>
                    //    q.GetType().GetProperty("ID").GetValue(q, null).Equals(ID)).SingleOrDefault();
                    TDB DBObject = TableObject.OfType<TDB>().Where(MakeFilter("ID", ID)).SingleOrDefault();

                    PropertyInfo IsDeletedProp = DBObject.GetType().GetProperty("IsDeleted");
                    if (IsDeletedProp != null)
                    {
                        IsDeletedProp.SetValue(DBObject, true, null);
                        db.SubmitChanges();
                    }
                    return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 19) };
                }
                catch(Exception ex)
                {
                    return Utility.logError(ex, 35, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                }
            }
        }
        public TDTO Get(int ID)
        {
            Type DTOType = typeof(TDTO);
            Type DBType = typeof(TDB);
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                try
                {
                    System.Data.Linq.ITable TableObject = db.GetTable(DBType);
                    TDB DBObject = TableObject.OfType<TDB>().ToList().Where(q =>
                        ID.ToString().Equals(q.GetType().GetProperty("ID").GetValue(q, null).ToString())
                        && q.GetType().GetProperty("IsDeleted").GetValue(q, null).Equals(false)).SingleOrDefault();
                    TDTO DTOObject = Activator.CreateInstance<TDTO>();
                    if (DBObject != null)
                    {
                        foreach (PropertyInfo Prop in DBType.GetProperties())
                        {
                            object Value = Prop.GetValue(DBObject, null);
                            //if (Value != null && DTOType.GetProperty(Prop.Name) != null && DBType.GetProperty(Prop.Name).PropertyType == DTOType.GetProperty(Prop.Name).PropertyType)//Value.GetType() == DTOType.GetProperty(Prop.Name).PropertyType)
                            //    DTOType.GetProperty(Prop.Name).SetValue(DTOObject, Value, null);

                            if (Value != null && DTOType.GetProperty(Prop.Name) != null && !Value.GetType().IsGenericType)
                            {
                                if (Prop.PropertyType.Name == DTOType.GetProperty(Prop.Name).PropertyType.Name)
                                    DTOType.GetProperty(Prop.Name).SetValue(DTOObject, Value, null);
                                else
                                {
                                    if (DTOType.GetProperty(Prop.Name) != null)
                                    {
                                        Type InnerDTOType = DTOType.GetProperty(Prop.Name).PropertyType;
                                        object innerDTOValue = Activator.CreateInstance(InnerDTOType);
                                        foreach (PropertyInfo InerProp in Prop.PropertyType.GetProperties())
                                        {
                                            //object innerDBValue = Value.GetType().GetProperty(InerProp.Name).GetValue(Value, null);
                                            object innerDBValue = InerProp.GetValue(Value, null);
                                            if (innerDBValue != null && InnerDTOType.GetProperty(InerProp.Name) != null && InnerDTOType.GetProperty(InerProp.Name).CanWrite)
                                            {
                                                if (InerProp.PropertyType == InnerDTOType.GetProperty(InerProp.Name).PropertyType)
                                                    //innerDBValue.GetType() == InnerDTOType.GetProperty(InerProp.Name).PropertyType
                                                    InnerDTOType.GetProperty(InerProp.Name).SetValue(innerDTOValue, innerDBValue, null);
                                            }
                                        }
                                        DTOType.GetProperty(Prop.Name).SetValue(DTOObject, innerDTOValue, null);
                                    }
                                }
                            }
                        }
                    }
                    return DTOObject;
                }
                catch(Exception ex)
                {
                    Utility.logError(ex,36 , System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                    return Activator.CreateInstance<TDTO>();
                }
            }
        }
        public List<TDTO> GetAll()
        {
            Type DTOType = typeof(TDTO);
            Type DBType = typeof(TDB);
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                try
                {
                    System.Data.Linq.ITable TableObject = db.GetTable(DBType);
                    //List<TDB> DBObjects = TableObject.OfType<TDB>().ToList().Where(q =>
                    //    q.GetType().GetProperty("IsDeleted").GetValue(q, null).Equals(false)).ToList();
                    List<TDB> DBObjects = TableObject.OfType<TDB>().Where(
                       MakeFilter("IsDeleted", false)).ToList();
                    List<TDTO> DTOObjects = new List<TDTO>();
                    foreach (TDB DBObject in DBObjects)
                    {
                        TDTO DTOObject = Activator.CreateInstance<TDTO>();
                        foreach (PropertyInfo Prop in DBType.GetProperties())
                        {
                            object Value = Prop.GetValue(DBObject, null);
                            if (Value != null && DTOType.GetProperty(Prop.Name) != null && DBType.GetProperty(Prop.Name).PropertyType == DTOType.GetProperty(Prop.Name).PropertyType)
                                DTOType.GetProperty(Prop.Name).SetValue(DTOObject, Value, null);
                        }

                        DTOObjects.Add(DTOObject);
                    }
                    return DTOObjects;
                }
                catch(Exception ex)
                {
                    Utility.logError(ex, 37, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                    return new List<TDTO>();
                }
            }
        }
        public List<TDTO> GetBaseOnProprety(string PropretyName, object PropretyValue)
        {
             Type DTOType = typeof(TDTO);
            Type DBType = typeof(TDB);
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                try
                {
                    System.Data.Linq.ITable TableObject = db.GetTable(DBType);                                      
                    List<TDB> DBObjects = TableObject.OfType<TDB>().Where(
                        MakeFilter("IsDeleted",false))
                        .Where(MakeFilter(PropretyName, PropretyValue)).ToList();
                    List<TDTO> DTOObjects = new List<TDTO>();
                    foreach (TDB DBObject in DBObjects)
                    {
                        TDTO DTOObject = Activator.CreateInstance<TDTO>();
                        foreach (PropertyInfo Prop in DBType.GetProperties())
                        {
                            object Value = Prop.GetValue(DBObject, null);
                            if (Value != null && DTOType.GetProperty(Prop.Name) != null && !Value.GetType().IsGenericType)
                            {                           
                                if(Prop.PropertyType.Name==DTOType.GetProperty(Prop.Name).PropertyType.Name)
                                      DTOType.GetProperty(Prop.Name).SetValue(DTOObject, Value, null);
                                else
                                {
                                    if (DTOType.GetProperty(Prop.Name) != null)
                                    {
                                        Type InnerDTOType = DTOType.GetProperty(Prop.Name).PropertyType;
                                        object innerDTOValue = Activator.CreateInstance(InnerDTOType);
                                        foreach (PropertyInfo InerProp in Prop.PropertyType.GetProperties())
                                        {
                                            //object innerDBValue = Value.GetType().GetProperty(InerProp.Name).GetValue(Value, null);
                                            object innerDBValue = InerProp.GetValue(Value, null);
                                            if (innerDBValue != null && InnerDTOType.GetProperty(InerProp.Name) != null && InnerDTOType.GetProperty(InerProp.Name).CanWrite)
                                            {
                                                if (InerProp.PropertyType == InnerDTOType.GetProperty(InerProp.Name).PropertyType)
                                                    //innerDBValue.GetType() == InnerDTOType.GetProperty(InerProp.Name).PropertyType
                                                    InnerDTOType.GetProperty(InerProp.Name).SetValue(innerDTOValue, innerDBValue, null);                                               
                                            }
                                        }
                                        DTOType.GetProperty(Prop.Name).SetValue(DTOObject, innerDTOValue, null);
                                    }
                                }
                            }
                        }

                        DTOObjects.Add(DTOObject);
                    }
                    return DTOObjects;
                }
                catch(Exception ex)
                {
                    Utility.logError(ex, 37, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                    return new List<TDTO>();
                }
            }
        }              
        static Expression<Func<TDB, bool>> MakeFilter(string propertyName, object value)
        {
            var type = typeof(TDB);

            var property = type.GetProperty(propertyName);

            var parameter = Expression.Parameter(type, "p");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var constantValue = Expression.Constant(value);

            var equality = Expression.Equal(propertyAccess, constantValue);

            return Expression.Lambda<Func<TDB, bool>>(equality, parameter);
        }
    }

    public interface ICRUD<TDTO>
    {
        ResultDTO<int> Add(TDTO Object);

        ResultDTO Update(TDTO Object);

        ResultDTO Delete(int ID);

        TDTO Get(int ID);

        List<TDTO> GetAll();
    }

    public class CRUDCar : ICRUD<CarDTO>
    {
        public ResultDTO<int> Add(CarDTO Object)
        {
            ResultDTO<int> Result = new ResultDTO<int>();
            try
            {
                using (var Scope = new TransactionScope())
                {
                    List<string> ImagesPath = Utility.UploadFiles();
                    Object.CarImages = ImagesPath.Select(q => new FileDTO { Path = q, TypeID = 1 }).ToList();
                    Result = new CRUD<CarDTO,Car>().Add(Object);
                    if (Result.IsSucceed.HasValue && Result.IsSucceed.Value)
                    {
                        bool ErrorOccured = false;

                        if (Object.CarImages != null)
                        {
                            Object.CarImages.ForEach
                                (q =>
                                    {
                                        var FileResult = new CRUD<FileDTO, File>().Add(q);
                                        if (FileResult.IsSucceed.HasValue && FileResult.IsSucceed.Value)
                                        {
                                            var ImageResult = new CRUD<CarImageDTO, CarImage>().Add(new CarImageDTO
                                            {
                                                CarID = Result.Data,
                                                FileID = FileResult.Data,
                                                IsDeleted = false
                                            });
                                            if (!ImageResult.IsSucceed.HasValue || !ImageResult.IsSucceed.Value)
                                            {
                                                ErrorOccured = true;
                                            }
                                        }
                                        else
                                        {
                                            ErrorOccured = true;
                                        }
                                    }
                                );
                        }
                        if (ErrorOccured)
                        {
                            Scope.Dispose();
                            return new ResultDTO<int> { Data = -1, IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 38) };
                        }
                        Scope.Complete();
                        return Result;
                    }
                    else
                    {
                         return new ResultDTO<int> { Data = -1, IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 38) }; 
                    }
                }
            }
            catch (Exception ex)
            {
                var ErorMessage = Utility.logError(ex, 38, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                Result.IsSucceed = ErorMessage.IsSucceed;
                Result.Message = ErorMessage.Message;
                Result.Data = -1;
            }
            return Result;
        }

        public ResultDTO Update(CarDTO Object)
        {
            ResultDTO Result = new ResultDTO();
            try
            {
                using (var Scope = new TransactionScope())
                {
                    List<string> ImagesPath = Utility.UploadFiles();
                    Object.CarImages = ImagesPath.Select(q => new FileDTO { Path = q, TypeID = 1 }).ToList();
                    Result = new CRUD<CarDTO, Car>().Update(Object);
                    if (Result.IsSucceed.HasValue && Result.IsSucceed.Value)
                    {
                        bool ErrorOccured = false;
                        if (Object.CarImages != null)
                        {
                            Object.CarImages.ForEach
                                (q =>
                                    {
                                        if (q.ID == 0)
                                        {
                                            var FileResult = new CRUD<FileDTO, File>().Add(q);
                                            if (FileResult.IsSucceed.HasValue && FileResult.IsSucceed.Value)
                                            {
                                                var ImageResult = new CRUD<CarImageDTO, CarImage>().Add(new CarImageDTO
                                                {
                                                    CarID = Object.ID,
                                                    FileID = FileResult.Data,
                                                    IsDeleted = false
                                                });
                                                if (!ImageResult.IsSucceed.HasValue || !ImageResult.IsSucceed.Value)
                                                {
                                                    ErrorOccured = true;
                                                }
                                            }
                                            else
                                            {
                                                ErrorOccured = true;
                                            }
                                        }
                                        else
                                        {
                                            var FileResult = new CRUD<FileDTO, File>().Update(q);
                                            if (!FileResult.IsSucceed.HasValue || !FileResult.IsSucceed.Value)
                                            {
                                                ErrorOccured = true;
                                            }
                                        }
                                    }
                                );
                        }
                        if (ErrorOccured)
                        {
                            Scope.Dispose();
                            return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 39) }; 
                        }
                        Scope.Complete();
                        return Result;
                    }
                    else
                    {
                        return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 39) }; 
                    }
                }
            }
            catch (Exception ex)
            {
                return Utility.logError(ex, 39, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);                
            }
        }

        public ResultDTO Delete(int ID)
        {
            try
            {

                string imgFolder = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
                var car = Get(ID);
                car.CarImages.ForEach(
                    q =>
                    {
                        string imgPath = System.IO.Path.Combine(imgFolder, q.Path.Replace('/', '\\').Remove(0, 2));
                        System.IO.File.Delete(imgPath);
                    });
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    var Car = db.Cars.Where(q => q.ID.Equals(ID)).SingleOrDefault();
                    Car.IsDeleted = true;
                    Car.CarImages.ToList().ForEach(q =>
                    {
                        q.IsDeleted = true;
                        q.File.IsDeleted = true;
                    });
                    db.SubmitChanges();
                }
                return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 19) };
            }
            catch (Exception ex)
            {
                return Utility.logError(ex, 35, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
        }

        public CarDTO Get(int ID)
        {
            var Result = new CRUD<CarDTO, Car>().Get(ID);
            var FileIDs = new CRUD<CarImageDTO, CarImage>().GetBaseOnProprety("CarID",ID).Select(q=>q.FileID).ToList();
            Result.CarImages = new List<FileDTO>();
            FileIDs.ForEach(q=>{
                var FileDTO = new CRUD<FileDTO, File>().Get((int)q);
                Result.CarImages.Add(FileDTO);
            });
            Result.Model = new CRUD<ModelDTO, Model>().Get(Result.ModelID);
            if (Result.StatusID.HasValue)
                Result.Status = new CRUD<CarStatusDTO, CarStatus>().Get(Result.StatusID.Value);
            return Result;
        }

        public List<CarDTO> GetAll()
        {
            return new CRUD<CarDTO, Car>().GetAll();
        }

        public PagingDTO<CarDTO> SerachCar(SerachCarDTO Condition,int start, int end,bool withTotal ,CarSortFeild? SortFeild, bool isAscending)
        {
            try
            {
                Func<Car, Object> orderByFunc = null;
                if (SortFeild != null)
                {
                    switch (SortFeild.Value)
                    {
                        case CarSortFeild.Brand:
                            orderByFunc = q => q.Model.Brand.Code;
                            break;
                        case CarSortFeild.Model:
                            orderByFunc = q => q.Model.Code;
                            break;
                        case CarSortFeild.Price:
                            orderByFunc = q => q.Price;
                            break;
                        case CarSortFeild.Usage:
                            orderByFunc = q => q.TraveledDistance;
                            break;
                        case CarSortFeild.Year:
                            orderByFunc = q => q.ProductYear;
                            break;
                        case CarSortFeild.StartDate:
                            orderByFunc = q => q.CarAnnouncement.StartDate;
                            break;
                    }
                }
                else
                {
                    orderByFunc = car => car.CarAnnouncement != null ?
                                                  20 * car.CarAnnouncement.CarAnnouncementTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - car.CarAnnouncement.StartDate.Value).TotalDays + 1)) :
                                                  20 * car.CarStore_Car.CarStore.CarStoreTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - car.CarStore_Car.CarStore.CreateDate.Value).TotalDays + 1));
                }
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    IEnumerable<Car> ResultQuery = (from car in db.Cars                                                                                                   
                                                  where
                                                  (car.CarAnnouncement != null ?
                                                  car.CarAnnouncement.IsActive && !car.CarAnnouncement.IsDeleted &&
                                                  (car.CarAnnouncement.StartDate.Value.Date < DateTime.Now) && (car.CarAnnouncement.FinishDate.Value.Date > DateTime.Now) 
                                                  :
                                                   car.CarStore_Car.CarStore.IsActive && !car.CarStore_Car.CarStore.IsDeleted &&
                                                   car.CarStore_Car.IsActive && !car.CarStore_Car.IsDeleted &&
                                                   (car.CarStore_Car.CarStore.CreateDate.Value.Date < DateTime.Now) && 
                                                  (car.CarStore_Car.CarStore.FinishDate.Value.Date > DateTime.Now)
                                                  )
                                                  &&
                                                  (car.Price >= Condition.PriceMin || !Condition.PriceMin.HasValue) &&
                                                  (car.Price <= Condition.PriceMax || !Condition.PriceMax.HasValue) &&
                                                  (car.ProductYear >= Condition.ProductYearMin || !Condition.ProductYearMin.HasValue) &&
                                                  (car.ProductYear <= Condition.ProductYearMax || !Condition.ProductYearMax.HasValue) &&
                                                  (car.TraveledDistance >= Condition.TraveledDistance_Min || !Condition.TraveledDistance_Min.HasValue) &&
                                                  (car.TraveledDistance <= Condition.TraveledDistance_Max || !Condition.TraveledDistance_Max.HasValue) &&
                                                  (car.ColorID == Condition.ColorID || !Condition.ColorID.HasValue) &&
                                                  (car.ModelID == Condition.ModelID || !Condition.ModelID.HasValue)
                                                  select car);
                   IOrderedEnumerable<Car> OrderedResult = SortFeild == null || isAscending ? ResultQuery.OrderBy(orderByFunc):
                        ResultQuery.OrderByDescending(orderByFunc);                    
                    List<CarDTO> ResultList = OrderedResult.Skip(start).Take(end- start).Select(car =>
                                                  new CarDTO
                                                  {
                                                      ID = car.ID,
                                                      Color = car.Color != null ? new ColorDTO { ID = car.Color.ID, Code = car.Color.Code } : null,
                                                      ColorID = car.ColorID,
                                                      Description = car.Description,
                                                      Model = new ModelDTO
                                                      {
                                                          ID = car.Model.ID,
                                                          Code = car.Model.Code,
                                                          Brand = new BrandDTO
                                                          { 
                                                              ID = car.Model.BrandID,
                                                              Code = car.Model.Brand.Code
                                                          }
                                                      },
                                                      ModelID = car.ModelID,
                                                      Price = car.Price,
                                                      ProductYear = car.ProductYear,
                                                      Status = car.CarStatus != null ? new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code } : null,
                                                      StatusID = car.StatusID,
                                                      TraveledDistance = car.TraveledDistance,
                                                      CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                                                  }).ToList();
                    int totalCount = 0;
                    if (withTotal)
                    {
                        totalCount = OrderedResult.Count();
                    }
                    return new PagingDTO<CarDTO>
                    {
                        Data = ResultList,
                        TotalCount = totalCount
                    };
                }
            }
            catch(Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }

        public bool IsCurrentUserOwnerOfCar(int carID)
        {
            if (Utility.GetLogginSession() == null)
                return false;
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                var Car = db.Cars.Where(q => q.ID.Equals(carID) && !q.IsDeleted).SingleOrDefault();
                if (Car != null)
                {
                    int OwnerID = Car.CarAnnouncement != null ? Car.CarAnnouncement.UserID : Car.CarStore_Car.CarStore.UserID;
                    if (OwnerID == Utility.GetLogginSession().ID)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }

        public UserDTO GetOwnerOfCar(int carID)
        {            
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                var Car = db.Cars.Where(q => q.ID.Equals(carID) && !q.IsDeleted).SingleOrDefault();
                if (Car != null)
                {
                    User Owner = Car.CarAnnouncement != null ? Car.CarAnnouncement.User : Car.CarStore_Car.CarStore.User;
                    return new UserDTO
                    {
                        FirstName = Owner.FirstName,
                        LastName = Owner.LastName,
                        Telephone = Owner.Telphone
                    };
                }
                else
                {
                    return null;
                }
            }
        }
    }

    public class ServiceCenter : ICRUD<ServiceCenterDTO>
    {

        public ResultDTO<int> Add(ServiceCenterDTO Object)
        {
            UserDTO CurrentUser = Common.Utility.GetLogginSession();
            if (CurrentUser != null)
            {
                Object.UserID = CurrentUser.ID;
                using (var Scope = new TransactionScope())
                {
                    string ImagePath = Utility.UploadFile();
                    if (!string.IsNullOrEmpty(ImagePath))
                        Object.File = new FileDTO { Path = ImagePath, TypeID = 1 };
                    if (Object.File != null)
                    {
                        var FileInsertResult = new CRUD<FileDTO, File>().Add(Object.File);
                        if (FileInsertResult.IsSucceed.HasValue && FileInsertResult.IsSucceed.Value)
                        {
                            Object.FileID = FileInsertResult.Data;
                        }
                        else
                        {
                            Object.FileID = null;
                        }
                    }

                    var Result = new CRUD<ServiceCenterDTO, KishOnlineDataAccess.ServiceCenter>().Add(Object);
                    if (Result.IsSucceed.HasValue && Result.IsSucceed.Value)
                    {
                        Scope.Complete();
                    }
                    else
                    {
                        Scope.Dispose();
                    }
                    return Result;
                }
            }
            else
            {
                // No loggin user exist;
                return new ResultDTO<int> { Data= -1,  IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 46) };
            }
        }

        public ResultDTO Update(ServiceCenterDTO Object)
        {
            string ImagePath = Utility.UploadFile();
            if (!string.IsNullOrEmpty(ImagePath))
                Object.File = new FileDTO { Path = ImagePath, TypeID = 1 };
            if (Object.File != null && Object.File.ID == 0)
            {
                var FileInsertResult = new CRUD<FileDTO, File>().Add(Object.File);
                if (FileInsertResult.IsSucceed.HasValue && FileInsertResult.IsSucceed.Value)
                {
                    Object.FileID = FileInsertResult.Data;
                }
                else
                {
                    Object.FileID = null;
                }
            }
            var Result = new CRUD<ServiceCenterDTO, KishOnlineDataAccess.ServiceCenter>().Update(Object);
            return Result;
        }

        public ResultDTO Delete(int ID)
        {
           return new CRUD<ServiceCenterDTO, KishOnlineDataAccess.ServiceCenter>().Delete(ID);
        }

        public ServiceCenterDTO Get(int ID)
        {
            ServiceCenterDTO Result = new ServiceCenterDTO();

            Result = new CRUD<ServiceCenterDTO, KishOnlineDataAccess.ServiceCenter>().Get(ID);
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                Result.Services = (from service in db.Services
                                   join serviceCenter_service in db.ServiceCenter_Services
                                   on service.ID equals serviceCenter_service.ServiceID
                                   join serviceCategory in db.ServiceCategories
                                   on service.ServiceCategoryID equals serviceCategory.ID
                                   where serviceCenter_service.ServiceCenterID.Equals(ID)
                                   && !service.IsDeleted
                                   select new ServiceDTO
                                   {
                                       ID = service.ID,
                                       ServiceCategoryID = service.ServiceCategoryID,
                                       ServiceCategory = new ServiceCategoryDTO
                                       {
                                           ID = serviceCategory.ID,
                                           Title = serviceCategory.Title,
                                           IsDeleted = false
                                       },
                                       Title = service.Title
                                   }).ToList();
            }
            return Result;
        }

        /// <summary>
        /// Get All Active ServiceCenter
        /// </summary>
        /// <returns></returns>
        public List<ServiceCenterDTO> GetAll()
        {
            List<ServiceCenterDTO> Result = new List<ServiceCenterDTO>();

            Result = new CRUD<ServiceCenterDTO, KishOnlineDataAccess.ServiceCenter>().GetAll();
            Result.RemoveAll(q => !q.IsActive);
            return Result;
        }

        public List<ServiceCenterDTO> GetInActiveServiceCenter()
        {
            List<ServiceCenterDTO> Result = new List<ServiceCenterDTO>();

            Result = new CRUD<ServiceCenterDTO, KishOnlineDataAccess.ServiceCenter>().GetAll();
            Result.RemoveAll(q => q.IsActive);
            return Result;
        }

        public ResultDTO ActivateServiceCenter(int ServiceCenterID)
        {
            var serviceCenter = Get(ServiceCenterID);
            serviceCenter.IsActive = true;
            var result = Update(serviceCenter);
            if (result.IsSucceed.HasValue && result.IsSucceed.Value)
            {
                result.Message = MessageReader.Get(MessageType.Event, 22);
            }
            else
            {
                result.Message = MessageReader.Get(MessageType.Error, 40);
            }
            return result;
        }
        
        public ResultDTO AddService(int ServiceCenterID, int ServiceID)
        {
            ResultDTO result = new ResultDTO();
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    db.ServiceCenter_Services.InsertOnSubmit(new ServiceCenter_Service
                    {
                        ServiceCenterID = ServiceCenterID,
                        ServiceID = ServiceID,
                    });
                    db.SubmitChanges();
                }
                result.IsSucceed = true;
                result.Message = MessageReader.Get(MessageType.Event, 20);
            }
            catch(Exception ex)
            {
                result = Utility.logError(ex, 41, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
            return result;
        }
        
        public ResultDTO DeleteService(int ServiceCenterID, int ServiceID)
        {
            ResultDTO result = new ResultDTO();
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    db.ServiceCenter_Services.DeleteOnSubmit(new ServiceCenter_Service
                    {
                        ServiceCenterID = ServiceCenterID,
                        ServiceID = ServiceID,
                    });
                    db.SubmitChanges();
                }
                result.IsSucceed = true;
                result.Message = MessageReader.Get(MessageType.Event, 21);
            }
            catch(Exception ex)
            {
               result = Utility.logError(ex, 42, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
            return result;
        }

        public PagingDTO<ServiceCenterDTO> SerachService(SerachServiceDTO Condition,int start, int end,bool withTotal ,ServiceCenterSorthFeild? SortFeild, bool isAscending)
        {
            try
            {
                Func<KishOnlineDataAccess.ServiceCenter, Object> orderByFunc = null;
                if (SortFeild != null)
                {
                    switch (SortFeild.Value)
                    {
                        case ServiceCenterSorthFeild.Name:
                            orderByFunc = q => q.Name;
                            break;                       
                    }
                }
                else
                {
                    orderByFunc = q => 20 * q.ServiceCenterTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - q.CreateDate.Value).TotalDays + 1));
                }
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    IEnumerable<KishOnlineDataAccess.ServiceCenter> ResultQuery = (from center in db.ServiceCenters
                                  join Cent_Svc in db.ServiceCenter_Services
                                  on center.ID equals Cent_Svc.ServiceCenterID
                                  join Svc in db.Services
                                  on Cent_Svc.ServiceID equals Svc.ID
                                  where
                                  center.IsActive && !center.IsDeleted && !Svc.IsDeleted &&
                                  (center.CreateDate <= DateTime.Now.Date) &&
                                  (DateTime.Now.Date <= center.FinishDate.Value.Date) &&
                                  (Svc.ServiceCategoryID.Equals(Condition.ServiceCategoryID)
                                  || !Condition.ServiceCategoryID.HasValue) &&
                                  (Svc.ServiceCategory.Title.Trim().ToUpper().Contains(Condition.ServiceCategoryTitle.Trim().ToUpper())
                                  || string.IsNullOrEmpty(Condition.ServiceCategoryTitle)) &&
                                  (Svc.Title.Trim().ToUpper().Contains(Condition.Title.Trim().ToUpper()) || string.IsNullOrEmpty(Condition.Title))
                                  select center); 
                    IOrderedEnumerable<KishOnlineDataAccess.ServiceCenter> OrderedResult = SortFeild == null || isAscending? ResultQuery.OrderBy(orderByFunc):
                        ResultQuery.OrderByDescending(orderByFunc);                    
                    List<ServiceCenterDTO> ResultList = OrderedResult.Skip(start).Take(end- start).             
                                  Select( q => new ServiceCenterDTO
                                  {
                                      ID = q.ID,
                                      Name = q.Name,
                                      Region = new RegionDTO { 
                                         ID = q.Region.ID,
                                         Title = q.Region.Title
                                      },
                                      RegionID = q.RegionID,
                                      Address = q.Address,
                                      CreateDate = q.CreateDate,
                                      CreateDateString = q.CreateDate.Value.ToShortDateString(),
                                      FileID = q.FileID,
                                      File = new FileDTO { 
                                          ID = q.File.ID,
                                          Path = q.File.Path
                                      },
                                      GoogleMapImageFileID = q.GoogleMapImageFileID,
                                      GoogleMapImageFile = new FileDTO
                                      {
                                          ID = q.File1.ID,
                                          Path = q.File1.Path
                                      },
                                      Telephone = q.Telephone,
                                      UserID = q.UserID,
                                      Services = q.ServiceCenter_Services.Select(p => new ServiceDTO
                                      {
                                          ID = p.Service.ID,
                                          Title = p.Service.Title
                                      }).ToList()
                                  }).ToList();
                    int totalCount = 0;
                    if (withTotal)
                    {
                        totalCount = OrderedResult.Count();
                    }
                    return new PagingDTO<ServiceCenterDTO>
                    {
                        Data = ResultList,
                        TotalCount = totalCount
                    };
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
        
        public PagingDTO<ServiceCenterDTO> SerachServiceCenter(SerachServiceCenterDTO Condition, int start, int end, bool withTotal, ServiceCenterSorthFeild? SortFeild, bool isAscending)
        {
            try
            {
                Func<KishOnlineDataAccess.ServiceCenter, Object> orderByFunc = null;
                if (SortFeild != null)
                {
                    switch (SortFeild.Value)
                    {
                        case ServiceCenterSorthFeild.Name:
                            orderByFunc = q => q.Name;
                            break;
                    }
                }
                else
                {
                    orderByFunc = q => 20 * q.ServiceCenterTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - q.CreateDate.Value).TotalDays + 1));
                }
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    IEnumerable<KishOnlineDataAccess.ServiceCenter> ResultQuery = (from center in db.ServiceCenters
                                                                                   where
                                                                                   center.IsActive && !center.IsDeleted &&
                                                                                   (center.CreateDate <= DateTime.Now.Date) &&
                                                                                   (DateTime.Now.Date <= center.FinishDate.Value.Date) &&
                                                                                   (Condition.Name == null || center.Name.ToUpper().Equals(Condition.Name.ToUpper())) &&
                                                                                   (Condition.Address == null || center.Address.ToUpper().Equals(Condition.Address.ToUpper())) &&
                                                                                   (Condition.Telephone == null || center.Telephone.ToUpper().Equals(Condition.Telephone.ToUpper()))
                                                                                   select center);

                    IOrderedEnumerable<KishOnlineDataAccess.ServiceCenter> OrderedResult = SortFeild== null || isAscending ? ResultQuery.OrderBy(orderByFunc) :
                ResultQuery.OrderByDescending(orderByFunc);
                    List<ServiceCenterDTO> ResultList = OrderedResult.Skip(start).Take(end - start).
                                  Select(center => new ServiceCenterDTO
                                  {
                                      ID = center.ID,
                                      Name = center.Name,
                                      Region = new RegionDTO
                                      {
                                          ID = center.Region.ID,
                                          Title = center.Region.Title
                                      },
                                      RegionID = center.RegionID,
                                      Address = center.Address,
                                      CreateDate = center.CreateDate,
                                      CreateDateString = center.CreateDate.Value.ToShortDateString(),
                                      FileID = center.FileID,
                                      File = new FileDTO
                                      {
                                          ID = center.File.ID,
                                          Path = center.File.Path
                                      },
                                      GoogleMapImageFileID = center.GoogleMapImageFileID,
                                      GoogleMapImageFile = new FileDTO
                                      {
                                          ID = center.File1.ID,
                                          Path = center.File1.Path
                                      },
                                      Telephone = center.Telephone,
                                      UserID = center.UserID
                                  }).ToList();
                    int totalCount = 0;
                    if (withTotal)
                    {
                        totalCount = OrderedResult.Count();
                    }
                    return new PagingDTO<ServiceCenterDTO>
                    {
                        Data = ResultList,
                        TotalCount = totalCount
                    };
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }

        public List<ServiceCenterDTO> GetServiceCentersOfCurrentUser()
        {            
            if (Utility.GetLogginSession() != null)
            {
                var result = new CRUD<ServiceCenterDTO, KishOnlineDataAccess.ServiceCenter>().GetBaseOnProprety("UserID", Utility.GetLogginSession().ID);
                return result;
            }
            else
            {
                return new List<ServiceCenterDTO>();
            }
        }
    }
    
    public class CarStore : ICRUD<CarStoreDTO>
    {

        public ResultDTO<int> Add(CarStoreDTO Object)
        {
            UserDTO CurrentUser = Common.Utility.GetLogginSession();
            if (CurrentUser != null)
            {
                Object.UserID = CurrentUser.ID;
                using (var Scope = new TransactionScope())
                {
                    string ImagePath = Utility.UploadFile();
                    if (!string.IsNullOrEmpty(ImagePath))
                        Object.File = new FileDTO { Path = ImagePath, TypeID = 1 };
                    if (Object.File != null)
                    {
                        var FileInsertResult = new CRUD<FileDTO, File>().Add(Object.File);
                        if (FileInsertResult.IsSucceed.HasValue && FileInsertResult.IsSucceed.Value)
                        {
                            Object.FileID = FileInsertResult.Data;
                        }
                        else
                        {
                            Object.FileID = null;
                        }
                    }
                    Object.IsActive = false;
                    var Result = new CRUD<CarStoreDTO, KishOnlineDataAccess.CarStore>().Add(Object);
                    if (Result.IsSucceed.HasValue && Result.IsSucceed.Value)
                    {
                        Scope.Complete();
                    }
                    else
                    {
                        Scope.Dispose();
                    }
                    return Result;
                }
            }
            else
            {
                // No loggin user exist;
                return new ResultDTO<int> { Data = -1, IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 47) }; 
            }
        }

        public ResultDTO Update(CarStoreDTO Object)
        {
            string ImagePath = Utility.UploadFile();
            if (!string.IsNullOrEmpty(ImagePath))
                Object.File = new FileDTO { Path = ImagePath, TypeID = 1 };
            if (Object.File != null && Object.File.ID == 0)
            {
                var FileInsertResult = new CRUD<FileDTO, File>().Add(Object.File);
                if (FileInsertResult.IsSucceed.HasValue && FileInsertResult.IsSucceed.Value)
                {
                    Object.FileID = FileInsertResult.Data;
                }
                else
                {
                    Object.FileID = null;
                }
            }
            Object.UserID = Utility.GetLogginSession().ID;            
            var Result = new CRUD<CarStoreDTO, KishOnlineDataAccess.CarStore>().Update(Object);
            return Result;
        }

        public ResultDTO Delete(int ID)
        {
            CarStoreDTO CurrentCarStore = Get(ID);
            if (Utility.GetLogginSession() != null && CurrentCarStore.UserID == Utility.GetLogginSession().ID)
            {
                try
                {
                    using (var Scope = new TransactionScope())
                    {
                        List<string> ImagesPath = new List<string>();
                        using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                        {
                            var CarStore = db.CarStores.Where(q => !q.IsDeleted && q.ID == ID).SingleOrDefault();
                            if (CarStore == null)
                                return Utility.logError(new Exception("CarStore Not Found in Delete Operation"), 6, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                            if (CarStore.File != null)
                                ImagesPath.Add(CarStore.File.Path);
                            CarStore.IsDeleted = true;
                            var CarsInCarStore = db.CarStore_Cars.Where(q => !q.IsDeleted && q.CarStoreID == ID).ToList();
                            CarsInCarStore.ForEach(q =>
                                {
                                    q.IsDeleted = true;
                                    ImagesPath.AddRange(q.Car.CarImages.Where(p => p.File != null).Select(p => p.File.Path).ToList());
                                    q.Car.IsDeleted = true;
                                    q.Car.CarImages.ToList().ForEach(p =>
                                        {
                                            p.IsDeleted = true;
                                            p.File.IsDeleted = true;
                                        });
                                });
                            db.SubmitChanges();
                        }

                        string imgFolder = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
                        ImagesPath.ForEach(
                        q =>
                        {
                            if (string.IsNullOrEmpty(q))
                            {
                                string imgPath = System.IO.Path.Combine(imgFolder, q.Replace('/', '\\').Remove(0, 2));
                                System.IO.File.Delete(imgPath);
                            }
                        });

                        Scope.Complete();                        
                    }
                    return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 2) };
                }
                catch (Exception ex)
                {
                    return Utility.logError(ex, 3,System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);                    
                }
            }
            else
            {
                return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 2) };
            }
        }

        public CarStoreDTO Get(int ID)
        {
            CarStoreDTO Result = new CarStoreDTO();

            Result = new CRUD<CarStoreDTO, KishOnlineDataAccess.CarStore>().Get(ID);
            if (Result.CreateDate.HasValue)
                Result.strCreateDate = Result.CreateDate.Value.Date.ToShortDateString();
            if (Result.FileID.HasValue)
            {
                Result.File = new CRUD<FileDTO, File>().Get((int)(Result.FileID.Value));
            }
            return Result;
        }

        /// <summary>
        /// Get All Active CarStore
        /// </summary>
        /// <returns></returns>
        public List<CarStoreDTO> GetAll()
        {
            List<CarStoreDTO> Result = new List<CarStoreDTO>();

            Result = new CRUD<CarStoreDTO, KishOnlineDataAccess.CarStore>().GetAll();
            Result.ForEach(q => q.strCreateDate = q.CreateDate.Value.Date.ToShortDateString());
            Result.RemoveAll(q => !q.IsActive);
            return Result;
        }
        
        public ResultDTO<int> AddCarToCarStore(int CarStoreID, CarDTO Car)
        {
            try
            {
                CarStoreDTO CurrentCarStore = Get(CarStoreID);
                if (Utility.GetLogginSession() != null && CurrentCarStore.UserID == Utility.GetLogginSession().ID)
                {
                    CarStore_CarDTO CarStore_NewCar = new CarStore_CarDTO();
                    using (var Scope = new System.Transactions.TransactionScope())
                    {
                        var CarInsertResult = new CRUDCar().Add(Car);
                        if (CarInsertResult.IsSucceed.HasValue && CarInsertResult.IsSucceed.Value)
                        {
                            CarStore_NewCar.CarID = CarInsertResult.Data;
                            CarStore_NewCar.CarStoreID = CarStoreID;
                            CarStore_NewCar.IsActive = false;
                            CarStore_NewCar.IsDeleted = false;
                            var Result = new CRUD<CarStore_CarDTO, CarStore_Car>().Add(CarStore_NewCar);
                            if (Result.IsSucceed.HasValue && Result.IsSucceed.Value)
                            {
                                Scope.Complete();
                            }
                            else
                            {
                                Scope.Dispose();
                            }
                            return Result;
                        }
                        else
                        {
                            // can not add car
                            Scope.Dispose();
                            return new ResultDTO<int> { Data = -1, IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 48) };
                        }
                    }
                }
                else
                {
                    return new ResultDTO<int> { Data = -1 , IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 2) };
                }
            }
            catch (Exception ex)
            {
                var Result = Utility.logError(ex, 48, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return new ResultDTO<int> { };
            }  
        }

        public ResultDTO UpdateCarInCarStore(int CarStoreID, CarDTO Car)
        {
            try
            {
                CarStoreDTO CurrentCarStore = Get(CarStoreID);
                if (Utility.GetLogginSession() != null && CurrentCarStore.UserID == Utility.GetLogginSession().ID )                    
                {
                    using (var scope = new TransactionScope())
                    {
                        var ResultCar = new CRUDCar().Update(Car);
                        if (ResultCar.IsSucceed == true)
                        {
                            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                            {
                                var CarInCarStore = db.CarStore_Cars.Where(q => !q.IsDeleted && q.CarID == Car.ID && q.CarStoreID == CarStoreID).SingleOrDefault();
                                if (CarInCarStore != null)
                                {
                                    CarInCarStore.IsActive = false;
                                    db.SubmitChanges();
                                }
                                else
                                {
                                    scope.Dispose();
                                    return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 2) };
                                }
                            }
                            scope.Complete();
                            return ResultCar;
                        }
                        else
                        {                            
                            scope.Dispose();
                            return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 27) };
                        }
                    }
                }
                else
                {
                    return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 2) };
                }
            }
            catch (Exception ex)
            {
                return Utility.logError(ex,27 , System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }  
        }

        public CarDTO GetCarInCarStore(int CarStoreID, int carID)
        {
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                var CarInCarStore = db.CarStore_Cars.Where(q => !q.IsDeleted && q.CarID == carID && q.CarStoreID == CarStoreID).SingleOrDefault();
                if (CarInCarStore == null)
                {
                    return null;
                }
            }
            
            CarStoreDTO CurrentCarStore = Get(CarStoreID);
            if (Utility.GetLogginSession() != null && CurrentCarStore.UserID == Utility.GetLogginSession().ID)
            {
                return new CRUDCar().Get(carID);
            }
            else
            {
                return null;
            }
        }

        public ResultDTO DeleteCarInCarStore(int CarStoreID, int carID)
        {
            using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
            {
                var CarInCarStore = db.CarStore_Cars.Where(q => !q.IsDeleted && q.CarID == carID && q.CarStoreID == CarStoreID).SingleOrDefault();
                if (CarInCarStore == null)
                {
                    return null;
                }
            }

            CarStoreDTO CurrentCarStore = Get(CarStoreID);
            if (Utility.GetLogginSession() != null && CurrentCarStore.UserID == Utility.GetLogginSession().ID)
            {
                using (var Scope = new TransactionScope())
                {
                    using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                    {
                        var CarInCarStore = db.CarStore_Cars.Where(q => !q.IsDeleted && q.CarID == carID && q.CarStoreID == CarStoreID).SingleOrDefault();
                        CarInCarStore.IsDeleted = true;
                        db.SubmitChanges();
                    }
                    ResultDTO DelcarResult = new CRUDCar().Delete(carID);
                    if (DelcarResult.IsSucceed == true)
                    {
                        Scope.Complete();
                        return DelcarResult;
                    }
                    else
                    {
                        Scope.Dispose();
                        return DelcarResult;
                    }
                }
            }
            else
            {
                return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 2) };
            }
        }

        public ResultDTO ActivateCarStore(int CarStoreID)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    var CarStore = db.CarStores.Where(q => q.ID.Equals(CarStoreID)).SingleOrDefault();
                    CarStore.IsActive = true;
                    CarStore.CreateDate = DateTime.Now.Date;
                    var Period = new CRUD<CarStoreTariffDTO, CarStoreTariff>().Get(CarStore.CarStoreTariffID).Period;
                    CarStore.FinishDate = DateTime.Now.Date.AddDays(Period);
                    db.SubmitChanges();
                } 
                return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 23) };
            }
            catch (Exception ex)
            {
                return Utility.logError(ex, 43, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }            
        }

        public ResultDTO ActivateCarStores(List<int> CarStoreIDs)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    var CarStore = db.CarStores.Where(q => CarStoreIDs.Contains(q.ID)).ToList();
                    CarStore.ForEach(q =>
                        {
                            q.IsActive = true;
                            q.CreateDate = DateTime.Now.Date;
                            var Period = new CRUD<CarStoreTariffDTO, CarStoreTariff>().Get(q.CarStoreTariffID).Period;
                            q.FinishDate = DateTime.Now.Date.AddDays(Period);
                        });
                    db.SubmitChanges();
                }
                return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 23) };
            }
            catch (Exception ex)
            {
                return Utility.logError(ex, 43, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
        }

        public ResultDTO ActivateCarInCarStore(int CarID)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    var CarStore_Car = db.CarStore_Cars.Where(q => q.CarID.Equals(CarID)).SingleOrDefault();
                    CarStore_Car.IsActive = true;
                    db.SubmitChanges();
                }
                return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 24) };
            }
            catch(Exception ex)
            {
                return Utility.logError(ex, 44, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
        }

        public ResultDTO ActivateCarsInCarStore(List<int> CarIDs)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    var CarStore_Cars = db.CarStore_Cars.Where(q => CarIDs.Contains(q.CarID)).ToList();
                    CarStore_Cars.ForEach(q => q.IsActive = true);
                    db.SubmitChanges();
                }
                return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 24) };
            }
            catch (Exception ex)
            {
                return Utility.logError(ex, 44, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
        }

        public PagingDTO<CarDTO> GetCarInCarStore(int CarStoreID,int start, int end, bool withTotal)
        {
            PagingDTO<CarDTO> result = new PagingDTO<CarDTO>();
            using (var db = Common.Utility.GetDataContext())
            {
               IQueryable<KishOnlineDataAccess.Car> ResultQuery = (from car in db.Cars
                          where car.CarStore_Car != null && !car.CarStore_Car.IsDeleted && car.CarStore_Car.CarStoreID == CarStoreID
                          select car);
               result.Data = ResultQuery.Skip(start).Take(end -start).Select(car => new CarDTO
                          {
                              ID = car.ID,
                              Color = car.Color != null ? new ColorDTO { ID = car.Color.ID, Code = car.Color.Code } : null,
                              ColorID = car.ColorID,
                              Description = car.Description,
                              Model = new ModelDTO
                              {
                                  ID = car.Model.ID,
                                  Code = car.Model.Code,
                                  Brand = new BrandDTO
                                  {
                                      ID = car.Model.BrandID,
                                      Code = car.Model.Brand.Code
                                  }
                              },
                              ModelID = car.ModelID,
                              Price = car.Price,
                              ProductYear = car.ProductYear,
                              Status = car.CarStatus != null ? new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code } : null,
                              StatusID = car.StatusID,
                              TraveledDistance = car.TraveledDistance,
                              CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                          }).ToList();
               if (withTotal)
               {
                   result.TotalCount = ResultQuery.Count();
               }
            }

            return result;
        }

        public PagingDTO<CarDTO> GetActiveCarInCarStore(int CarStoreID, int start, int end, bool withTotal)
        {
            return GetInCarStore(CarStoreID, start, end, withTotal, q => q.CarStore_Car.IsActive);
        }

        public PagingDTO<CarDTO> GetInActiveCarInCarStore(int CarStoreID, int start, int end, bool withTotal)
        {
            return GetInCarStore(CarStoreID, start, end, withTotal, q => !q.CarStore_Car.IsActive);
        }

        private PagingDTO<CarDTO> GetInCarStore(int CarStoreID, int start, int end, bool withTotal,Func<KishOnlineDataAccess.Car,bool> Condition)
        {
            PagingDTO<CarDTO> result = new PagingDTO<CarDTO>();
            using (var db = Common.Utility.GetDataContext())
            {
                IEnumerable<KishOnlineDataAccess.Car> ResultQuery = (from car in db.Cars
                                                                    where car.CarStore_Car != null && !car.CarStore_Car.IsDeleted && car.CarStore_Car.CarStoreID == CarStoreID
                                                                    select car).Where(Condition);
                result.Data = ResultQuery.Skip(start).Take(end - start).Select(car => new CarDTO
                {
                    ID = car.ID,
                    Color = car.Color != null ? new ColorDTO { ID = car.Color.ID, Code = car.Color.Code } : null,
                    ColorID = car.ColorID,
                    Description = car.Description,
                    Model = new ModelDTO
                    {
                        ID = car.Model.ID,
                        Code = car.Model.Code,
                        Brand = new BrandDTO
                        {
                            ID = car.Model.BrandID,
                            Code = car.Model.Brand.Code
                        }
                    },
                    ModelID = car.ModelID,
                    Price = car.Price,
                    ProductYear = car.ProductYear,
                    Status = car.CarStatus != null ? new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code } : null,
                    StatusID = car.StatusID,
                    TraveledDistance = car.TraveledDistance,
                    CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                }).ToList();
                if (withTotal)
                {
                    result.TotalCount = ResultQuery.Count();
                }
            }

            return result;
        }        

        public PagingDTO<CarStoreDTO> GetInActiveStores(string StoreName, int Start, int End, bool WithTotal)
        {
            PagingDTO<CarStoreDTO> Result = new PagingDTO<CarStoreDTO>();
            using (var db = Common.Utility.GetDataContext())
            {
                IQueryable<KishOnlineDataAccess.CarStore> CarStore = db.CarStores.Where(q => !q.IsDeleted && !q.IsActive);
                if (!string.IsNullOrEmpty(StoreName))
                {
                    CarStore = CarStore.Where(q => q.Name.Trim().ToUpper().Contains(StoreName.Trim().ToUpper()));
                }
                Result.Data = CarStore.Skip(Start).Take(End - Start).Select(q => new CarStoreDTO
                    {
                        File = q.File != null ? new FileDTO
                        {
                            ID = q.File.ID,
                            Path = q.File.Path
                        }: null,
                        ID = q.ID,
                        Email = q.Email,
                        Name = q.Name,
                        ManagerName = q.ManagerName,
                        NameOfFormFiller = q.NameOfFormFiller,
                        Province = q.Province != null ? new ProvinceDTO
                        {
                            ID = q.Province.ID,
                            Code = q.Province.Code
                        } : null,
                        Telephone = q.Telephone,
                        Address = q.Address,
                        Description = q.Description
                    }).ToList();
                if (WithTotal)
                {
                    Result.TotalCount = CarStore.Count();
                }
            }
           
            return Result;
        }

        public bool VisitCountIncrement(int CarStoreID)
        {
            try
            {
                using (var db = Common.Utility.GetDataContext())
                {
                    var CarStore = db.CarStores.Where(q => q.ID.Equals(CarStoreID)).SingleOrDefault();
                    CarStore.VisitCount++;
                    db.SubmitChanges();
                }
                return true;
            }
            catch(Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return false;
            }
            
        }

        public PagingDTO<CarStoreDTO> SerachCarStore(SerachCarStoreDTO Condition, int start, int end, bool withTotal, CarStoreSortFeild? SortFeild, bool isAscending)
        {
            try
            {
                Func<KishOnlineDataAccess.CarStore, Object> orderByFunc = null;
                if (SortFeild != null)
                {
                    switch (SortFeild.Value)
                    {
                        case CarStoreSortFeild.Name:
                            orderByFunc = q => q.Name;
                            break;                                        
                    }
                }
                else
                {
                    orderByFunc = q => 20 * q.CarStoreTariff.PriorityCoefficient * (1 / ((DateTime.Now - q.CreateDate.Value).TotalDays + 1));
                }
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    IEnumerable<KishOnlineDataAccess.CarStore> ResultQuery = (from carstor in db.CarStores
                                                  join traf in db.CarStoreTariffs
                                                  on carstor.CarStoreTariffID equals traf.ID
                                                  join Image in db.Files
                                                  on carstor.FileID equals Image.ID
                                                  orderby 20 * traf.PriorityCoefficient * (1 / ((DateTime.Now - carstor.CreateDate.Value).TotalDays + 1))
                                                  where
                                                  carstor.IsActive && !carstor.IsDeleted &&
                                                  (carstor.CreateDate.Value.Date < DateTime.Now) && (carstor.FinishDate.Value.Date > DateTime.Now)&&
                                                  ((carstor.Address == null)||(carstor.Address.ToUpper().Contains(Condition.Address.ToUpper()))) &&
                                                  ((carstor.Description == null)||(carstor.Description.ToUpper().Contains(Condition.Description.ToUpper()))) &&
                                                  ((carstor.Email == null)||(carstor.Email.ToUpper().Contains(Condition.Email.ToUpper()))) &&
                                                  ((carstor.ManagerName == null)||(carstor.ManagerName.ToUpper().Contains(Condition.ManagerName.ToUpper()))) &&
                                                  ((carstor.Name == null)||(carstor.Address.ToUpper().Contains(Condition.Name.ToUpper()))) &&
                                                  ((carstor.Telephone == null)||(carstor.Telephone.ToUpper().Contains(Condition.Telephone.ToUpper()))) &&
                                                  ((carstor.ProvinceID == 0)||(carstor.ProvinceID == Condition.ProvinceID))                                               
                                                  select carstor).Distinct();
                     IOrderedEnumerable<KishOnlineDataAccess.CarStore> OrderedResult = SortFeild == null || isAscending ? ResultQuery.OrderBy(orderByFunc):
                        ResultQuery.OrderByDescending(orderByFunc);
                     List<CarStoreDTO> ResultList = OrderedResult.Skip(start).Take(end - start).Select(carstor =>
                                                   new CarStoreDTO
                                                  {
                                                      ID = carstor.ID,
                                                      Address = carstor.Address,
                                                      Description = carstor.Description,
                                                      Email = carstor.Email,
                                                      FileID = carstor.FileID,                                                    
                                                      Telephone = carstor.Telephone,
                                                      ManagerName = carstor.ManagerName,
                                                      Name = carstor.Name,
                                                      File = carstor.FileID != null ? new FileDTO
                                                      {
                                                          ID = carstor.FileID.Value,
                                                          Path = carstor.File.Path,
                                                          TypeID = carstor.File.TypeID
                                                      } : null                                                     
                                                  }).ToList();
                     int totalCount = 0;
                     if (withTotal)
                     {
                         totalCount = OrderedResult.Count();
                     }
                     return new PagingDTO<CarStoreDTO>
                     {
                         Data = ResultList,
                         TotalCount = totalCount
                     };
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
       
        public PagingDTO<CarStoreDTO> GetCarStoresOfCurrentUser(int Start, int End, bool WithTotal)
        {
            PagingDTO<CarStoreDTO> Result = new PagingDTO<CarStoreDTO>();
            if (Utility.GetLogginSession() != null)
            {
                using (var db = Common.Utility.GetDataContext())
                {
                    IQueryable<KishOnlineDataAccess.CarStore> CarStore = db.CarStores.Where(q => !q.IsDeleted && q.UserID.Equals(Utility.GetLogginSession().ID)).OrderBy(q => q.Name.Trim().ToUpper());                   
                    Result.Data = CarStore.Skip(Start).Take(End - Start).Select(q => new CarStoreDTO
                    {
                        File = q.File != null ? new FileDTO
                        {
                            ID = q.File.ID,
                            Path = q.File.Path
                        } : null,
                        ID = q.ID,
                        Email = q.Email,
                        Name = q.Name,
                        ManagerName = q.ManagerName,
                        NameOfFormFiller = q.NameOfFormFiller,
                        Province = q.Province != null ? new ProvinceDTO
                        {
                            ID = q.Province.ID,
                            Code = q.Province.Code
                        } : null,
                        Telephone = q.Telephone,
                        Address = q.Address,
                        IsActive = q.IsActive
                    }).ToList();
                    if (WithTotal)
                    {
                        Result.TotalCount = CarStore.Count();
                    }
                }
            }
            return Result;
        }
    }

    public class CarAnnouncement
    {
        public ResultDTO<int> Add(CarAnnouncementDTO Annoncment)
        {
            UserDTO CurrentUser = Common.Utility.GetLogginSession();
            if (CurrentUser != null)
            {
                Annoncment.UserID = CurrentUser.ID;
                using (var Scope = new TransactionScope())
                {
                    var CarInsertResult = new CRUDCar().Add(Annoncment.Car);
                    if (CarInsertResult.IsSucceed.HasValue && CarInsertResult.IsSucceed.Value)
                    {
                        Annoncment.CarID = CarInsertResult.Data;
                        var Result = new CRUD<CarAnnouncementDTO, KishOnlineDataAccess.CarAnnouncement>().Add(Annoncment);
                        if (Result.IsSucceed.HasValue && Result.IsSucceed.Value)
                        {
                            Scope.Complete();
                        }
                        else
                        {
                            Scope.Dispose();
                        }
                        return Result;
                    }
                    else
                    {
                        // can not add car
                        Scope.Dispose();
                        return new ResultDTO<int> { Data = -1, IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 48) };
                    }

                }
            }
            else
            {
                // No loggin user exist;
                return new ResultDTO<int> { Data = -1, IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 47) };
            }

        }

        public ResultDTO Update(CarAnnouncementDTO Object)
        {
            using (var db = Common.Utility.GetDataContext())
            {
                int carID = Object.CarID > 0 ? Object.CarID : Object.Car.ID;
                var CarAnnounc = db.CarAnnouncements.Where(q => q.CarID.Equals(carID)).SingleOrDefault();
                if (CarAnnounc.UserID != Utility.GetLogginSession().ID )
                {
                    return new ResultDTO { IsSucceed = false, Message = MessageReader.Get(MessageType.Error, 2) };
                }
            }
            using (var Scope = new TransactionScope())
            {
                int CurrentUserID = Utility.GetLogginSession().ID;                
                var UpdateCarResult = new CRUDCar().Update(Object.Car);
                if (UpdateCarResult.IsSucceed.HasValue && UpdateCarResult.IsSucceed.Value)
                {                    
                    try
                    {
                        using (var db = Common.Utility.GetDataContext())
                        {
                            int carID = Object.CarID > 0 ? Object.CarID : Object.Car.ID;
                            var CarAnnounc = db.CarAnnouncements.Where(q => q.CarID.Equals(carID)).SingleOrDefault();
                            
                                CarAnnounc.CarAnnouncementTariffID = Object.CarAnnouncementTariffID;
                                CarAnnounc.StartDate = Object.StartDate;
                                CarAnnounc.FinishDate = Object.FinishDate;
                                CarAnnounc.IsActive = false;
                                db.SubmitChanges();                            
                        }
                        Scope.Complete();
                        return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 18) };
                    }
                    catch(Exception ex)
                    {
                        Scope.Dispose();
                        return Utility.logError(ex, 34, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                    }
                }
                else
                {
                    Scope.Dispose();
                    return UpdateCarResult;
                }
            }
        }

        public ResultDTO Delete(int ID)
        {                       
            try
            {
                using (var scope = new TransactionScope())
                {
                    string imgFolder = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
                    var data = Get(ID);
                    data.Car.CarImages.ForEach(
                        q =>
                        {
                            string imgPath = System.IO.Path.Combine(imgFolder, q.Path.Replace('/', '\\').Remove(0, 2));
                            System.IO.File.Delete(imgPath);
                        });
                    using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                    {
                        var ann = db.CarAnnouncements.Where(q => q.CarID.Equals(ID)).SingleOrDefault();
                        ann.IsDeleted = true;
                        ann.Car.IsDeleted = true;
                        db.SubmitChanges();
                    }
                    scope.Complete();
                }
                return new ResultDTO { IsSucceed = true, Message = MessageReader.Get(MessageType.Event, 19) };
            }
            catch (Exception ex)
            {
                return Utility.logError(ex, 35, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
        }
        
        public CarAnnouncementDTO Get(int CarID)
        {
            var result = new CRUD<CarAnnouncementDTO, KishOnlineDataAccess.CarAnnouncement>().GetBaseOnProprety("CarID", CarID).FirstOrDefault();
            if (result != null)
                result.Car = new CRUDCar().Get(CarID);
            return result;
        }

        public ResultDTO ActivateAnnouncement(int carID)
        {
            try
            {
                ResultDTO result = new ResultDTO();
                using (var db = Common.Utility.GetDataContext())
                {
                    KishOnlineDataAccess.CarAnnouncement Announcemen = db.CarAnnouncements.Where(q => q.CarID == carID).SingleOrDefault();
                    Announcemen.IsActive = true;
                    Announcemen.StartDate = DateTime.Now.Date;
                    var Period = new CRUD<CarAnnouncementTariffDTO, CarAnnouncementTariff>().Get(Announcemen.CarAnnouncementTariffID).Period;
                    Announcemen.FinishDate = DateTime.Now.Date.AddDays(Period);
                    db.SubmitChanges();
                    result.Message = MessageReader.Get(MessageType.Event, 25);
                    result.IsSucceed = true;
                }
                return result;
            }
            catch (Exception ex)
            {               
                return Utility.logError(ex, 45, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
        }

        public ResultDTO ActivateAnnouncements(List<int> carIDs)
        {
            try
            {
               
                ResultDTO result = new ResultDTO();
                using (var db = Common.Utility.GetDataContext())
                {
                    List<KishOnlineDataAccess.CarAnnouncement> Announcemen = db.CarAnnouncements.Where(q => carIDs.Contains(q.CarID)).ToList();
                    Announcemen.ForEach(q =>
                    {
                        q.IsActive = true;
                        q.StartDate = DateTime.Now.Date;
                        var Period = new CRUD<CarAnnouncementTariffDTO, CarAnnouncementTariff>().Get(q.CarAnnouncementTariffID).Period;
                        q.FinishDate = DateTime.Now.Date.AddDays(Period);
                    });
                    db.SubmitChanges();
                    result.Message = MessageReader.Get(MessageType.Event, 25);
                    result.IsSucceed = true;
                }
                return result;
            }
            catch (Exception ex)
            {
                return Utility.logError(ex, 45, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
            }
        }

        public bool VisitCountIncrement(int CarID)
        {
            //var Announcemen = new CRUD<CarAnnouncementDTO, KishOnlineDataAccess.CarAnnouncement>().Get(AnnouncementID);
            var Announcemen = this.Get(CarID);
            Announcemen.VisitCount++;
            var result = this.Update(Announcemen);
            
            return result.IsSucceed.Value;
        }

        public PagingDTO<InActiveCarsDTO> GetInActiveAnnouncement(string Owner, int? carModelID, int start, int end, bool withtotal)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    IEnumerable<InActiveCarsDTO> InactiveCarsQuery = (from car in db.Cars
                                                                      let owner = car.CarAnnouncement != null ? car.CarAnnouncement.User.FirstName + car.CarAnnouncement.User.FirstName
                                                                          //: (car.CarStore_Car != null ? car.CarStore_Car.CarStore.Name : null)
                                                                      : car.CarStore_Car.CarStore.Name
                                                                      let isInCarStore = car.CarAnnouncement != null ? false : true
                                                                      where
                                                                      (car.CarAnnouncement != null || car.CarStore_Car != null) &&
                                                                      car.CarAnnouncement != null ?
                                                                      !car.CarAnnouncement.IsDeleted && !car.CarAnnouncement.IsActive
                                                                      : !car.CarStore_Car.IsDeleted && !car.CarStore_Car.IsActive && car.CarStore_Car.CarStore.IsActive
                                                                      && (string.IsNullOrEmpty(Owner) || owner.Trim().ToUpper().Contains(Owner.Trim().ToUpper()))
                                                                      // && (carModelID.HasValue ? car.ModelID == carModelID.Value: true)
                                                                      select new InActiveCarsDTO
                                                                        {
                                                                            Car = new CarDTO
                                                                            {
                                                                                ID = car.ID,
                                                                                CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                                                                                Color = car.ColorID == null ? null : new ColorDTO { ID = car.Color.ID, Code = car.Color.Code },
                                                                                Description = car.Description,
                                                                                KeyWords = car.KeyWords,
                                                                                Price = car.Price,
                                                                                ProductYear = car.ProductYear,
                                                                                Status = car.StatusID == null ? null : new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code },
                                                                                TraveledDistance = car.TraveledDistance,
                                                                                Model = new ModelDTO
                                                                                {
                                                                                    ID = car.Model.ID,
                                                                                    Code = car.Model.Code
                                                                                }
                                                                            },
                                                                            Owner = car.CarAnnouncement != null ? car.CarAnnouncement.User.FirstName + car.CarAnnouncement.User.FirstName
                                                                                    : car.CarStore_Car.CarStore.Name,
                                                                            IsInCarStore = isInCarStore
                                                                        });
                    InactiveCarsQuery = carModelID.HasValue ? InactiveCarsQuery.Where(q => q.Car.ModelID == carModelID.Value) : InactiveCarsQuery;
                    List<InActiveCarsDTO> InactiveCars = InactiveCarsQuery.Skip(start).Take(end - start).ToList();
                    int totalCount = 0;
                    if (withtotal)
                    {
                        totalCount = InactiveCarsQuery.Count();
                    }
                    return new PagingDTO<InActiveCarsDTO>
                    {
                        Data = InactiveCars,
                        TotalCount = totalCount
                    };
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return new PagingDTO<InActiveCarsDTO>();
            }
        }
        
        public ResultDTO ExtendAnnouncement(int AnnouncementID, DateTime ExtendDate)
        {
            throw new NotImplementedException();
        }

        public PagingDTO<CarAnnouncementDTO> GetAnnouncementsOfCurrentUser(int start, int end, bool WithTotal)
        {        
            try
            {
                int CurrentUserID = Utility.GetLogginSession().ID;
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    IQueryable<CarAnnouncementDTO> Query = (from ann in db.CarAnnouncements
                                                 join car in db.Cars on ann.CarID equals car.ID
                                                 join images in db.CarImages on car.ID equals images.CarID 
                                                 into carImages from carImage in carImages.DefaultIfEmpty()                                                 
                                                 where !ann.IsDeleted && ann.UserID.Equals(CurrentUserID)
                                                 group new { ann, carImages, car } by ann into Group
                                                 select new CarAnnouncementDTO
                                                 {
                                                     Car = new CarDTO
                                                     {
                                                         ID = Group.Key.CarID,
                                                         CarImages = Group.Key.Car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                                                         Color = Group.First().car.ColorID == null ? null:new ColorDTO { ID = Group.First().car.Color.ID, Code = Group.First().car.Color.Code },
                                                         Description = Group.First().car.Description,
                                                         KeyWords = Group.First().car.KeyWords,
                                                         Price = Group.First().car.Price,
                                                         ProductYear = Group.First().car.ProductYear,
                                                         Status = Group.First().car.StatusID == null ? null : new CarStatusDTO { ID = Group.First().car.CarStatus.ID, Code = Group.First().car.CarStatus.Code },
                                                         TraveledDistance = Group.First().car.TraveledDistance,
                                                         Model = new ModelDTO
                                                         {
                                                             ID = Group.First().car.Model.ID,
                                                             Code = Group.First().car.Model.Code
                                                         }
                                                     },
                                                     CarAnnouncementTariff = new CarAnnouncementTariffDTO
                                                     {
                                                         Description = Group.Key.CarAnnouncementTariff.Description,
                                                         Title = Group.Key.CarAnnouncementTariff.Title,
                                                         ShowVistCount = Group.Key.CarAnnouncementTariff.ShowVistCount,
                                                         PriorityCoefficient = Group.Key.CarAnnouncementTariff.PriorityCoefficient
                                                     },
                                                     UserID = CurrentUserID,
                                                     CarAnnouncementTariffID = Group.Key.CarAnnouncementTariffID,
                                                     StartDate = Group.Key.StartDate,
                                                     strStartDate = Group.Key.StartDate.HasValue ? Group.Key.StartDate.Value.Date.ToShortDateString() : "",
                                                     FinishDate = Group.Key.FinishDate,
                                                     strFinishDate = Group.Key.FinishDate.HasValue ? Group.Key.FinishDate.Value.Date.ToShortDateString() : "",
                                                     IsActive = Group.Key.IsActive,
                                                     VisitCount = Group.Key.VisitCount,
                                                 });

                    List<CarAnnouncementDTO> AnnoncmentCurrentUser = Query.Skip(start).Take(end - start).ToList();
                    return new PagingDTO<CarAnnouncementDTO>
                    {
                        Data = AnnoncmentCurrentUser,
                        TotalCount = Query.Count()
                    };
                }                
            }
            catch(Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return new PagingDTO<CarAnnouncementDTO>();
            }
        }
    }

    public class SerachAll
    {
        //public static SerachAllDTO SerachAllEntity(string txt, int start, int end, bool withTotal, bool SortByStartDate, bool isAscending)
        //{
        //    SerachAllDTO Result = new SerachAllDTO();
        //    Result.Car = SerachAllCar(txt, start, end, withTotal, SortByStartDate, isAscending);
        //    Result.CarStore = SerachALLCarStore(txt, start, end, withTotal, SortByStartDate, isAscending);
        //    Result.ServiceCenter = SerachALLService(txt, start, end, withTotal, SortByStartDate, isAscending);
        //    return Result;
        //}
        public static PagingDTO<ServiceCenterDTO> SerachALLService(string txt, int start, int end, bool withTotal, bool SortByStartDate, bool isAscending)
        {
            try
            {    
                Func<KishOnlineDataAccess.ServiceCenter, Object> orderByFunc = null;
                if (SortByStartDate)
                {
                    orderByFunc = q => q.CreateDate;
                }
                else
                {
                    orderByFunc = q => 20 * q.ServiceCenterTariff.PriorityCoefficient * (1 / ((DateTime.Now - q.CreateDate.Value).TotalDays + 1));
                }         
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    
                    IEnumerable<KishOnlineDataAccess.ServiceCenter> ResultQuery = (from center in db.ServiceCenters
                                  join Cent_Svc in db.ServiceCenter_Services
                                  on center.ID equals Cent_Svc.ServiceCenterID
                                  join Svc in db.Services
                                  on Cent_Svc.ServiceID equals Svc.ID
                                  where
                                  center.IsActive && !center.IsDeleted && !Svc.IsDeleted &&
                                  (center.CreateDate <= DateTime.Now.Date) &&
                                  (DateTime.Now.Date <= center.FinishDate.Value.Date) &&
                                  (Svc.Title.ToUpper().Contains(txt.ToUpper())||
                                   Svc.ServiceCategory.Title.ToUpper().Contains(txt.ToUpper())||
                                   center.Telephone.ToUpper().Contains(txt.ToUpper())||
                                   center.Address.ToUpper().Contains(txt.ToUpper())||
                                   center.Name.ToUpper().Contains(txt.ToUpper()))
                                   select center).Distinct();
                    IOrderedEnumerable<KishOnlineDataAccess.ServiceCenter> OrderedResult = !SortByStartDate || isAscending ? ResultQuery.OrderBy(orderByFunc) :
                     ResultQuery.OrderByDescending(q => q.CreateDate);
                    List<ServiceCenterDTO> ResultList = OrderedResult.Skip(start).Take(end - start).Select(q=>new ServiceCenterDTO
                                  {
                                      ID = q.ID,
                                      Name = q.Name,
                                      Region = new RegionDTO
                                      {
                                          ID = q.Region.ID,
                                          Title = q.Region.Title
                                      },
                                      RegionID = q.RegionID,
                                      Address = q.Address,
                                      CreateDate = q.CreateDate,
                                      CreateDateString = q.CreateDate != null ? q.CreateDate.Value.ToShortDateString() : string.Empty,
                                      FileID = q.FileID,
                                      File = q.File != null ? new FileDTO
                                      {
                                          ID = q.File.ID,
                                          Path = q.File.Path
                                      } : null,
                                      GoogleMapImageFileID = q.GoogleMapImageFileID,
                                      GoogleMapImageFile = q.File1 != null ? new FileDTO
                                      {
                                          ID = q.File1.ID,
                                          Path = q.File1.Path
                                      } : null,
                                      Telephone = q.Telephone,
                                      UserID = q.UserID,
                                      Services = q.ServiceCenter_Services.Select(p => new ServiceDTO
                                      {
                                          ID = p.Service.ID,
                                          Title = p.Service.Title
                                      }).ToList()
                                  }).ToList();
                    int totalCount = 0;
                    if (withTotal)
                    {
                        totalCount = OrderedResult.Count();
                    }
                    return new PagingDTO<ServiceCenterDTO>
                    {
                        Data = ResultList,
                        TotalCount = totalCount
                    };
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
        public static PagingDTO<CarStoreDTO> SerachALLCarStore(string txt, int start, int end, bool withTotal, bool SortByStartDate, bool isAscending)
        {
            try
            {
                Func<KishOnlineDataAccess.CarStore, Object> orderByFunc = null;
                if (SortByStartDate)
                {
                    orderByFunc = q => q.CreateDate;
                }
                else
                {
                    orderByFunc = carstor => 20 * carstor.CarStoreTariff.PriorityCoefficient * (1 / ((DateTime.Now - carstor.CreateDate.Value).TotalDays + 1));
                }
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    
                    IEnumerable<KishOnlineDataAccess.CarStore> ResultQuery = (from carstor in db.CarStores
                                           where
                                           carstor.IsActive && !carstor.IsDeleted &&
                                           (carstor.CreateDate.Value.Date < DateTime.Now) && (carstor.FinishDate.Value.Date > DateTime.Now) &&
                                           ((carstor.Address.ToUpper().Contains(txt.ToUpper())) ||
                                           (carstor.Description.ToUpper().Contains(txt.ToUpper())) ||
                                           (carstor.Email.ToUpper().Contains(txt.ToUpper())) ||
                                           (carstor.ManagerName.ToUpper().Contains(txt.ToUpper())) ||
                                           (carstor.Name.ToUpper().Contains(txt.ToUpper())) ||
                                           (carstor.Telephone.ToUpper().Contains(txt.ToUpper())))
                                           select carstor);
                    IOrderedEnumerable<KishOnlineDataAccess.CarStore> OrderedResult = !SortByStartDate || isAscending ? ResultQuery.OrderBy(orderByFunc) :
                     ResultQuery.OrderByDescending(orderByFunc);
                    List<CarStoreDTO> ResultList = OrderedResult.Skip(start).Take(end - start).Select(carstor=> new CarStoreDTO
                                           {
                                               ID = carstor.ID,
                                               Address = carstor.Address,
                                               Description = carstor.Description,
                                               Email = carstor.Email,
                                               FileID = carstor.FileID,
                                               Telephone = carstor.Telephone,
                                               ManagerName = carstor.ManagerName,
                                               Name = carstor.Name,
                                               File = carstor.FileID != null ? new FileDTO
                                               {
                                                   ID = carstor.FileID.Value,
                                                   Path = carstor.File.Path,
                                                   TypeID = carstor.File.TypeID
                                               } : null
                                           }).ToList();
                    int totalCount = 0;
                    if (withTotal)
                    {
                        totalCount = OrderedResult.Count();
                    }
                    return new PagingDTO<CarStoreDTO>
                    {
                        Data = ResultList,
                        TotalCount = totalCount
                    };                    
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
        public static PagingDTO<CarDTO> SerachAllCar(string txt, int start, int end, bool withTotal, bool SortByStartDate, bool isAscending)
        {
            try
            {
                Func<Car, Object> orderByFunc = null;
                if (SortByStartDate)
                {
                    orderByFunc = q => q.CarAnnouncement.StartDate;
                }
                else
                {
                    orderByFunc = car => car.CarAnnouncement != null ?
                                                  20 * car.CarAnnouncement.CarAnnouncementTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - car.CarAnnouncement.StartDate.Value).TotalDays + 1)) :
                                                  20 * car.CarStore_Car.CarStore.CarStoreTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - car.CarStore_Car.CarStore.CreateDate.Value).TotalDays + 1));
                }
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    
                    IEnumerable<Car> ResultQuery = (from car in db.Cars
                                                  where
                                                  (car.CarAnnouncement != null ?
                                                  car.CarAnnouncement.IsActive && !car.CarAnnouncement.IsDeleted &&
                                                  (car.CarAnnouncement.StartDate.Value.Date < DateTime.Now) && (car.CarAnnouncement.FinishDate.Value.Date > DateTime.Now)
                                                  :
                                                   car.CarStore_Car.CarStore.IsActive && !car.CarStore_Car.CarStore.IsDeleted &&
                                                   car.CarStore_Car.IsActive && !car.CarStore_Car.IsDeleted &&
                                                   (car.CarStore_Car.CarStore.CreateDate.Value.Date < DateTime.Now) &&
                                                  (car.CarStore_Car.CarStore.FinishDate.Value.Date > DateTime.Now)
                                                  ) &&
                                                  (car.Description.ToUpper().Contains(txt.ToUpper()) ||                                                  
                                                  car.Model.Code.ToUpper().Contains(txt.ToUpper()) ||
                                                  car.Model.Brand.Code.ToUpper().Contains(txt.ToUpper()))
                                                  select car);
                    IOrderedEnumerable<Car> OrderedResult = !SortByStartDate || isAscending ? ResultQuery.OrderBy(orderByFunc) :
                     ResultQuery.OrderByDescending(orderByFunc);
                    List<CarDTO> ResultList = OrderedResult.Skip(start).Take(end - start).Select(car =>
                                                  new CarDTO
                                                  {
                                                      ID = car.ID,
                                                      Color = car.Color != null ? new ColorDTO { ID = car.Color.ID, Code = car.Color.Code } : null,
                                                      ColorID = car.ColorID,
                                                      Description = car.Description,
                                                      Model = new ModelDTO
                                                      {
                                                          ID = car.Model.ID,
                                                          Code = car.Model.Code,
                                                          Brand = new BrandDTO
                                                          {
                                                              ID = car.Model.BrandID,
                                                              Code = car.Model.Brand.Code
                                                          }
                                                      },
                                                      ModelID = car.ModelID,
                                                      Price = car.Price,
                                                      ProductYear = car.ProductYear,
                                                      Status = car.CarStatus != null ? new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code } : null,
                                                      StatusID = car.StatusID,
                                                      TraveledDistance = car.TraveledDistance,
                                                      CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                                                  }).ToList();
                    int totalCount = 0;
                    if (withTotal)
                    {
                        totalCount = OrderedResult.Count();
                    }
                    return new PagingDTO<CarDTO>
                    {
                        Data = ResultList,
                        TotalCount = totalCount
                    };                    
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }       
    }
    
    public class GetRelated
    {
        public static AllRelatedEntityDTO GetRelatedEntity(object Entity)
        {
            string Keywords = "";
            if (Entity is CarDTO)
                Keywords = new CRUDCar().Get((Entity as CarDTO).ID).KeyWords;
            else if (Entity is CarStoreDTO)
                Keywords = new CarStore().Get((Entity as CarStoreDTO).ID).KeyWords;
            else if (Entity is ServiceCenterDTO)
                Keywords = new ServiceCenter().Get((Entity as ServiceCenterDTO).ID).KeyWords;
            else return new AllRelatedEntityDTO();
            if (!string.IsNullOrEmpty(Keywords))
            {
                AllRelatedEntityDTO Result = new AllRelatedEntityDTO();
                Result.Car = SerachRelatedCar(Keywords);
                Result.CarStore = SerachRelatedCarStore(Keywords);
                Result.ServiceCenter = SerachRelatedService(Keywords);
                return Result;
            }
            else
                return new AllRelatedEntityDTO();
        }
        private static List<ServiceCenterDTO> SerachRelatedService(string KeyWords)
        {
            try
            {                                               
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {                    
                    IEnumerable<KishOnlineDataAccess.ServiceCenter> ResultQuery = (from center in db.ServiceCenters
                                  join Cent_Svc in db.ServiceCenter_Services
                                  on center.ID equals Cent_Svc.ServiceCenterID
                                  join Svc in db.Services
                                  on Cent_Svc.ServiceID equals Svc.ID
                                  orderby 20 * center.ServiceCenterTariff.PriorityCoefficient * (1 / ((DateTime.Now - center.CreateDate.Value).TotalDays + 1))
                                  where
                                  center.IsActive && !center.IsDeleted && !Svc.IsDeleted &&
                                  (center.CreateDate <= DateTime.Now.Date) &&
                                  (DateTime.Now.Date <= center.FinishDate.Value.Date) &&
                                  (db.KeyWordsIntersect(center.KeyWords, KeyWords).Value)
                                  select center).Distinct().Take(20);
                    List<ServiceCenterDTO> ResultList = ResultQuery.Select(q => new ServiceCenterDTO
                    {
                        ID = q.ID,
                        Name = q.Name,
                        Region = new RegionDTO
                        {
                            ID = q.Region.ID,
                            Title = q.Region.Title
                        },
                        RegionID = q.RegionID,
                        Address = q.Address,
                        CreateDate = q.CreateDate,
                        CreateDateString = q.CreateDate!= null ? q.CreateDate.Value.ToShortDateString():string.Empty,
                        FileID = q.FileID,
                        File = q.File!= null ? new FileDTO
                        {
                            ID = q.File.ID,
                            Path = q.File.Path
                        }: null,
                        GoogleMapImageFileID = q.GoogleMapImageFileID,
                        GoogleMapImageFile =  q.File1!= null ?new FileDTO
                        {
                            ID = q.File1.ID,
                            Path = q.File1.Path
                        }: null,
                        Telephone = q.Telephone,
                        UserID = q.UserID,
                        Services = q.ServiceCenter_Services.Select(p => new ServiceDTO
                        {
                            ID = p.Service.ID,
                            Title = p.Service.Title
                        }).ToList()
                    }).ToList();
                    return ResultList;
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
        private static List<CarStoreDTO> SerachRelatedCarStore(string KeyWords)
        {
            try
            {                
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    
                    var CarStoresResult = (from carstor in db.CarStores
                                           orderby 20 * carstor.CarStoreTariff.PriorityCoefficient * (1 / ((DateTime.Now - carstor.CreateDate.Value).TotalDays + 1))
                                           where
                                           carstor.IsActive && !carstor.IsDeleted &&
                                           (carstor.CreateDate.Value.Date < DateTime.Now) && (carstor.FinishDate.Value.Date > DateTime.Now) &&
                                           (db.KeyWordsIntersect(carstor.KeyWords, KeyWords).Value)
                                           select new CarStoreDTO
                                           {
                                               ID = carstor.ID,
                                               Address = carstor.Address,
                                               Description = carstor.Description,
                                               Email = carstor.Email,
                                               FileID = carstor.FileID,
                                               Telephone = carstor.Telephone,
                                               ManagerName = carstor.ManagerName,
                                               Name = carstor.Name,
                                               File = carstor.FileID != null ? new FileDTO
                                               {
                                                   ID = carstor.FileID.Value,
                                                   Path = carstor.File.Path,
                                                   TypeID = carstor.File.TypeID
                                               } : null
                                           }).Take(20).ToList();
                    return CarStoresResult;
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
        private static List<CarDTO> SerachRelatedCar(string KeyWords)
        {
            try
            {
                //KeyWords = KeyWords.Select(q => q.Trim().ToUpper()).ToList();
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    //
                    IEnumerable<Car> ResultQuery  = (from car in db.Cars                                                                                                                                                    
                                                  orderby 
                                                  car.CarAnnouncement != null ?
                                                  20 * car.CarAnnouncement.CarAnnouncementTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - car.CarAnnouncement.StartDate.Value).TotalDays + 1)) :
                                                  20 * car.CarStore_Car.CarStore.CarStoreTariff.PriorityCoefficient *
                                                  (1 / ((DateTime.Now - car.CarStore_Car.CarStore.CreateDate.Value).TotalDays + 1))
                                                  where
                                                  (car.CarAnnouncement != null ?
                                                  car.CarAnnouncement.IsActive && !car.CarAnnouncement.IsDeleted &&
                                                  (car.CarAnnouncement.StartDate.Value.Date < DateTime.Now) && (car.CarAnnouncement.FinishDate.Value.Date > DateTime.Now)
                                                  :
                                                   car.CarStore_Car.CarStore.IsActive && !car.CarStore_Car.CarStore.IsDeleted &&
                                                   car.CarStore_Car.IsActive && !car.CarStore_Car.IsDeleted &&
                                                   (car.CarStore_Car.CarStore.CreateDate.Value.Date < DateTime.Now) &&
                                                  (car.CarStore_Car.CarStore.FinishDate.Value.Date > DateTime.Now)
                                                  )
                                                  &&
                                                  (db.KeyWordsIntersect(car.KeyWords,KeyWords).Value)                                                   
                                                     select car).Take(20);
                    List<CarDTO> ResultList = ResultQuery.Select(car =>
                                                  new CarDTO
                                                  {
                                                      ID = car.ID,
                                                      Color = car.Color != null ? new ColorDTO { ID = car.Color.ID, Code = car.Color.Code } : null,
                                                      ColorID = car.ColorID,
                                                      Description = car.Description,
                                                      Model = new ModelDTO
                                                      {
                                                          ID = car.Model.ID,
                                                          Code = car.Model.Code,
                                                          Brand = new BrandDTO
                                                          {
                                                              ID = car.Model.BrandID,
                                                              Code = car.Model.Brand.Code
                                                          }
                                                      },
                                                      ModelID = car.ModelID,
                                                      Price = car.Price,
                                                      ProductYear = car.ProductYear,
                                                      Status = car.CarStatus != null ? new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code } : null,
                                                      StatusID = car.StatusID,
                                                      TraveledDistance = car.TraveledDistance,
                                                      CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                                                  }).ToList();
                    return ResultList;
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
    }

    public class TopAll
    {
        public static AllRelatedEntityDTO GetTopEntity(int Count)
        {          
            
                AllRelatedEntityDTO Result = new AllRelatedEntityDTO();
                Result.Car = SerachTopCar(Count);
                Result.CarStore = SerachTopCarStore(Count);
                Result.ServiceCenter = SerachTopService(Count);
                return Result;            
        }
        private static List<ServiceCenterDTO> SerachTopService(int Count)
        {
            try
            {                
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    
                    IEnumerable<KishOnlineDataAccess.ServiceCenter> ResultQuery = (from center in db.ServiceCenters
                                                                                   join Cent_Svc in db.ServiceCenter_Services
                                                                                   on center.ID equals Cent_Svc.ServiceCenterID
                                                                                   join Svc in db.Services
                                                                                   on Cent_Svc.ServiceID equals Svc.ID
                                                                                   orderby 20 * center.ServiceCenterTariff.PriorityCoefficient * (1 / ((DateTime.Now - center.CreateDate.Value).TotalDays + 1))
                                                                                   where
                                                                                   center.IsActive && !center.IsDeleted && !Svc.IsDeleted &&
                                                                                   (center.CreateDate <= DateTime.Now.Date) &&
                                                                                   (DateTime.Now.Date <= center.FinishDate.Value.Date) 
                                                                                   select center).Distinct().Take(Count);
                    List<ServiceCenterDTO> ResultList = ResultQuery.Select(q => new ServiceCenterDTO
                    {
                        ID = q.ID,
                        Name = q.Name,
                        Region = new RegionDTO
                        {
                            ID = q.Region.ID,
                            Title = q.Region.Title
                        },
                        RegionID = q.RegionID,
                        Address = q.Address,
                        CreateDate = q.CreateDate,
                        CreateDateString = q.CreateDate.Value.ToShortDateString(),
                        FileID = q.FileID,
                        File = new FileDTO
                        {
                            ID = q.File.ID,
                            Path = q.File.Path
                        },
                        GoogleMapImageFileID = q.GoogleMapImageFileID,
                        GoogleMapImageFile = new FileDTO
                        {
                            ID = q.File1.ID,
                            Path = q.File1.Path
                        },
                        Telephone = q.Telephone,
                        UserID = q.UserID,
                        Services = q.ServiceCenter_Services.Select(p => new ServiceDTO
                        {
                            ID = p.Service.ID,
                            Title = p.Service.Title
                        }).ToList()
                    }).ToList();
                    return ResultList;
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
        private static List<CarStoreDTO> SerachTopCarStore(int Count)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    
                    var CarStoresResult = (from carstor in db.CarStores
                                           orderby 20 * carstor.CarStoreTariff.PriorityCoefficient * (1 / ((DateTime.Now - carstor.CreateDate.Value).TotalDays + 1))
                                           where
                                           carstor.IsActive && !carstor.IsDeleted &&
                                           (carstor.CreateDate.Value.Date < DateTime.Now) && (carstor.FinishDate.Value.Date > DateTime.Now) 
                                           select new CarStoreDTO
                                           {
                                               ID = carstor.ID,
                                               Address = carstor.Address,
                                               Description = carstor.Description,
                                               Email = carstor.Email,
                                               FileID = carstor.FileID,
                                               Telephone = carstor.Telephone,
                                               ManagerName = carstor.ManagerName,
                                               Name = carstor.Name,
                                               File = carstor.FileID != null ? new FileDTO
                                               {
                                                   ID = carstor.FileID.Value,
                                                   Path = carstor.File.Path,
                                                   TypeID = carstor.File.TypeID
                                               } : null
                                           }).Take(Count).ToList();
                    return CarStoresResult;
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
        private static List<CarDTO> SerachTopCar(int Count)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    
                    IEnumerable<Car> ResultQuery = (from car in db.Cars
                                                    orderby
                                                    car.CarAnnouncement != null ?
                                                    20 * car.CarAnnouncement.CarAnnouncementTariff.PriorityCoefficient *
                                                    (1 / ((DateTime.Now - car.CarAnnouncement.StartDate.Value).TotalDays + 1)) :
                                                    20 * car.CarStore_Car.CarStore.CarStoreTariff.PriorityCoefficient *
                                                    (1 / ((DateTime.Now - car.CarStore_Car.CarStore.CreateDate.Value).TotalDays + 1))
                                                    where
                                                    (car.CarAnnouncement != null ?
                                                    car.CarAnnouncement.IsActive && !car.CarAnnouncement.IsDeleted &&
                                                    (car.CarAnnouncement.StartDate.Value.Date < DateTime.Now) && (car.CarAnnouncement.FinishDate.Value.Date > DateTime.Now)
                                                    :
                                                     car.CarStore_Car.CarStore.IsActive && !car.CarStore_Car.CarStore.IsDeleted &&
                                                     car.CarStore_Car.IsActive && !car.CarStore_Car.IsDeleted &&
                                                     (car.CarStore_Car.CarStore.CreateDate.Value.Date < DateTime.Now) &&
                                                    (car.CarStore_Car.CarStore.FinishDate.Value.Date > DateTime.Now)
                                                    )
                                                    select car).Take(Count);
                    List<CarDTO> ResultList = ResultQuery.Select(car =>
                                                  new CarDTO
                                                  {
                                                      ID = car.ID,
                                                      Color = car.Color != null ? new ColorDTO { ID = car.Color.ID, Code = car.Color.Code } : null,
                                                      ColorID = car.ColorID,
                                                      Description = car.Description,
                                                      Model = new ModelDTO
                                                      {
                                                          ID = car.Model.ID,
                                                          Code = car.Model.Code,
                                                          Brand = new BrandDTO
                                                          {
                                                              ID = car.Model.BrandID,
                                                              Code = car.Model.Brand.Code
                                                          }
                                                      },
                                                      ModelID = car.ModelID,
                                                      Price = car.Price,
                                                      ProductYear = car.ProductYear,
                                                      Status = car.CarStatus != null ? new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code } : null,
                                                      StatusID = car.StatusID,
                                                      TraveledDistance = car.TraveledDistance,
                                                      CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                                                  }).ToList();
                    return ResultList;
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return null;
            }
        }
    }

    public class AdminTasks
    {
        public PagingDTO<InActiveCarsDTO> GetInActiveAnnouncement(string Owner, string carModel, int start, int end, bool withtotal)
        {
            try
            {
                using (var db = KishOnlineDomain.Common.Utility.GetDataContext())
                {
                    IEnumerable<InActiveCarsDTO> InactiveCarsQuery = (from car in db.Cars
                                                                      let owner = car.CarAnnouncement != null ? car.CarAnnouncement.User.FirstName + " " + car.CarAnnouncement.User.LastName                                                                        
                                                                      : car.CarStore_Car.CarStore.Name
                                                                      let isInCarStore = car.CarAnnouncement != null ? false : true
                                                                      where
                                                                      (car.CarAnnouncement != null || car.CarStore_Car != null) &&
                                                                      (car.CarAnnouncement != null ?
                                                                      !car.CarAnnouncement.IsDeleted && !car.CarAnnouncement.IsActive
                                                                      : !car.CarStore_Car.IsDeleted && !car.CarStore_Car.IsActive && car.CarStore_Car.CarStore.IsActive)
                                                                      && (string.IsNullOrEmpty(Owner) || owner.Trim().ToUpper().Contains(Owner.Trim().ToUpper()))
                                                                      && (string.IsNullOrEmpty(carModel) || car.Model.Code.Trim().ToUpper().Contains(carModel.Trim().ToUpper()))
                                                                      select new InActiveCarsDTO
                                                                      {
                                                                          Car = new CarDTO
                                                                          {
                                                                              ID = car.ID,
                                                                              CarImages = car.CarImages.Select(q => new FileDTO { ID = q.File.ID, Path = q.File.Path }).ToList(),
                                                                              Color = car.ColorID == null ? null : new ColorDTO { ID = car.Color.ID, Code = car.Color.Code },
                                                                              Description = car.Description,
                                                                              KeyWords = car.KeyWords,
                                                                              Price = car.Price,
                                                                              ProductYear = car.ProductYear,
                                                                              Status = car.StatusID == null ? null : new CarStatusDTO { ID = car.CarStatus.ID, Code = car.CarStatus.Code },
                                                                              TraveledDistance = car.TraveledDistance,
                                                                              Model = new ModelDTO
                                                                              {
                                                                                  ID = car.Model.ID,
                                                                                  Code = car.Model.Code
                                                                              }
                                                                          },
                                                                          Owner = owner,
                                                                          IsInCarStore = isInCarStore
                                                                      });                    
                    List<InActiveCarsDTO> InactiveCars = InactiveCarsQuery.Skip(start).Take(end - start).ToList();
                    int totalCount = 0;
                    if (withtotal)
                    {
                        totalCount = InactiveCarsQuery.Count();
                    }
                    return new PagingDTO<InActiveCarsDTO>
                    {
                        Data = InactiveCars,
                        TotalCount = totalCount
                    };
                }
            }
            catch (Exception ex)
            {
                Utility.logError(ex, System.Reflection.MethodInfo.GetCurrentMethod().ReflectedType.FullName);
                return new PagingDTO<InActiveCarsDTO>();
            }
        }
    }
}
